using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using System.Data;
using Sinacor.Infra.Service.Data;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.Service.Common;

namespace Sinacor.Service.Infra.AuthorizationService.ResourceAccess
{

    /// <summary>
    /// Business Logic BehaviorPolicy
    /// </summary>
    public class BehaviorPolicy : BaseResourceAccess
    {
        #region Construtor

        /// <summary>
        /// Construtor padrão
        /// </summary>
        public BehaviorPolicy()
            : base(AuthorizationContext.Current.CompanyId)
        {
        }


        /// <summary>
        /// Construtor sobrecarregado que recebe o id da company
        /// </summary>
        public BehaviorPolicy(int companyId)
            : base(companyId)
        {
        }

        #endregion


        #region InsertBehaviorPolicy
        /// <summary>
        /// Método InsertBehaviorPolicy
        /// </summary>
        public void InsertBehaviorPolicy(BusinessEntity.BehaviorPolicy request)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine(@"INSERT 
							INTO
							TFWEPERM_POL_ACES
							(
							COD_PERM,
							COD_POL_ACES,
							IND_PERM_EDIC_DADO,
							IND_VISI_DADO
							)
							VALUES
							(
							:COD_PERM,
							:COD_POL_ACES,
							:IND_PERM_EDIC_DADO,
							:IND_VISI_DADO
							)
							");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "COD_PERM", DbType.String, request.RoleId);
                this.DataBase.AddInParameter(command, "COD_POL_ACES", DbType.Int32, request.AssociatedPolicy);
                this.DataBase.AddInParameter(command, "IND_PERM_EDIC_DADO", DbType.Int32, request.IsEditable.Value ? 1 : 0);
                this.DataBase.AddInParameter(command, "IND_VISI_DADO", DbType.Int32, request.IsVisible.Value ? 1 : 0);

                this.DataBase.ExecuteNonQuery(command);

            }


        }

        #endregion


        #region UpdateBehaviorPolicy
        /// <summary>
        /// Método UpdateBehaviorPolicy
        /// </summary>
        public void UpdateBehaviorPolicy(BusinessEntity.BehaviorPolicy request)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine(@"
							UPDATE 
							TFWEPERM_POL_ACES
							SET  COD_PERM = :COD_PERM
							    ,COD_POL_ACES = :COD_POL_ACES
							    ,IND_PERM_EDIC_DADO = :IND_PERM_EDIC_DADO
							    ,IND_VISI_DADO = :IND_VISI_DADO
							");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "COD_PERM", DbType.String, request.RoleId);
                this.DataBase.AddInParameter(command, "COD_POL_ACES", DbType.Int32, request.AssociatedPolicy);
                this.DataBase.AddInParameter(command, "IND_PERM_EDIC_DADO", DbType.Int32, request.IsEditable.Value ? 1 : 0);
                this.DataBase.AddInParameter(command, "IND_VISI_DADO", DbType.Int32, request.IsVisible.Value ? 1 : 0);

                this.DataBase.ExecuteNonQuery(command);

            }


        }

        #endregion


        #region DeleteBehaviorPolicy
        /// <summary>
        /// Método DeleteBehaviorPolicy
        /// </summary>
        public void DeleteBehaviorPolicy(BusinessEntity.BehaviorPolicy request)
        {
            StringBuilder sql = new StringBuilder();

            sql.AppendLine(@"DELETE 
							TFWEPERM_POL_ACES
							WHERE
							COD_PERM = :COD_PERM
							AND
							COD_POL_ACES = :COD_POL_ACES");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "COD_PERM", DbType.String, request.RoleId);
                this.DataBase.AddInParameter(command, "COD_POL_ACES", DbType.Int32, request.AssociatedPolicy);

                this.DataBase.ExecuteNonQuery(command);

            }


        }

        #endregion


        #region RetrieveBehaviorPolicy
        /// <summary>
        /// Método RetrieveBehaviorPolicy
        /// </summary>
        public BusinessEntity.BehaviorPolicy RetrieveBehaviorPolicy(BusinessEntity.BehaviorPolicy request)
        {
            BusinessEntity.BehaviorPolicy response = null;
            StringBuilder sql = new StringBuilder();

            sql.AppendLine(@"SELECT ");
            sql.AppendLine(this.DataBase.GetCompanyId().ToString() + @" AS ""COMPANY_ID"", ");
            sql.AppendLine(@"A.COD_PERM,
							A.COD_POL_ACES,
							A.IND_PERM_EDIC_DADO,
							A.IND_VISI_DADO,
                            B.NOME_POL_ACES,
                            B.IND_SITU_POL_ACES,
                            B.COD_TIPO_POL_ACES
							FROM
							TFWEPERM_POL_ACES A
                            INNER JOIN
                            TFWSPOL_ACES B
                            ON 
                            A.COD_POL_ACES = B.COD_POL_ACES
                            WHERE
							A.COD_PERM = :COD_PERM
							AND
							A.COD_POL_ACES = :COD_POL_ACES");

            using (DbCommand command = this.DataBase.GetSqlStringCommand(sql.ToString()))
            {
                this.DataBase.AddInParameter(command, "COD_PERM", DbType.String, request.RoleId);
                this.DataBase.AddInParameter(command, "COD_POL_ACES", DbType.Int32, request.AssociatedPolicy.PolicyId);

                response = this.FindOne<BusinessEntity.BehaviorPolicy>(command, new ConstructEntity<BusinessEntity.BehaviorPolicy>(ConstrutorBehaviorPolicy));
            }

            return response;
        }

        #endregion

        #region RetrieveBehaviorPolicies

        /// <summary>
        /// Método RetrieveBehaviorPolicies
        /// </summary>
        public List<BusinessEntity.BehaviorPolicy> RetrieveBehaviorPolicies(BusinessEntity.BehaviorPolicy request)
        {
            List<BusinessEntity.BehaviorPolicy> response = null;
            StringBuilder sql = new StringBuilder();

            using (DbCommand command = this.DataBase.GetSqlStringCommand(" "))
            {

                sql.AppendLine(@"SELECT ");
                sql.AppendLine(this.DataBase.GetCompanyId().ToString() + @" AS ""COMPANY_ID"", ");
                sql.AppendLine(@"A.COD_PERM,
							A.COD_POL_ACES,
							A.IND_PERM_EDIC_DADO,
							A.IND_VISI_DADO,
                            B.NOME_POL_ACES,
                            B.IND_SITU_POL_ACES,
                            B.COD_TIPO_POL_ACES
							FROM
							TFWEPERM_POL_ACES A
                            INNER JOIN
                            TFWSPOL_ACES B
                            ON 
                            A.COD_POL_ACES = B.COD_POL_ACES");

                //se informou uma role
                if (!string.IsNullOrEmpty(request.RoleId))
                {
                    sql.AppendLine("WHERE");
                    sql.AppendLine("COD_PERM = :COD_PERM");

                    this.DataBase.AddInParameter(command, "COD_PERM", DbType.String, request.RoleId);
                }


                if (request.AssociatedPolicy != null && request.AssociatedPolicy.PolicyId.HasValue)
                {
                    if (!sql.ToString().Contains("WHERE"))
                        sql.AppendLine("WHERE ");
                    else
                        sql.AppendLine("AND ");

                    sql.AppendLine("COD_POL_ACES = :COD_POL_ACES");

                    this.DataBase.AddInParameter(command, "COD_POL_ACES", DbType.Int32, request.AssociatedPolicy.PolicyId);
                }

                if (request.IsEditable.HasValue)
                {
                    if (!sql.ToString().Contains("WHERE"))
                        sql.AppendLine("WHERE ");
                    else
                        sql.AppendLine("AND ");

                    sql.AppendLine("IND_PERM_EDIC_DADO = :IND_PERM_EDIC_DADO");

                    this.DataBase.AddInParameter(command, "IND_PERM_EDIC_DADO", DbType.Int32, request.IsEditable.Value ? 1 : 0);
                }

                if (request.IsVisible.HasValue)
                {
                    if (!sql.ToString().Contains("WHERE"))
                        sql.AppendLine("WHERE ");
                    else
                        sql.AppendLine("AND ");

                    sql.AppendLine("IND_VISI_DADO = :IND_VISI_DADO");

                    this.DataBase.AddInParameter(command, "IND_VISI_DADO", DbType.Int32, request.IsVisible.Value ? 1 : 0);
                }


                command.CommandText = sql.ToString();

                response = this.FindAll<BusinessEntity.BehaviorPolicy>(command, new ConstructEntity<BusinessEntity.BehaviorPolicy>(ConstrutorBehaviorPolicy));
            }

            return response;
        }

        #endregion

        #region RetrieveUserBehaviorPolicies
        /// <summary>
        /// Método RetrieveBehaviorPolicies
        /// </summary>
        public List<BusinessEntity.BehaviorPolicy> RetrieveUserBehaviorPolicies(List<string> roles)
        {
            if (roles == null || roles.Count == 0)
                return null;

            List<BusinessEntity.BehaviorPolicy> response = null;
            StringBuilder sql = new StringBuilder();

            using (DbCommand command = this.DataBase.GetSqlStringCommand(" "))
            {

                sql.AppendLine(@"SELECT ");
                sql.AppendLine(this.DataBase.GetCompanyId().ToString() + @" AS ""COMPANY_ID"", ");
                sql.AppendLine(@"A.COD_PERM,
							A.COD_POL_ACES,
							A.IND_PERM_EDIC_DADO,
							A.IND_VISI_DADO,
                            B.NOME_POL_ACES,
                            B.IND_SITU_POL_ACES,
                            B.COD_TIPO_POL_ACES
							FROM
							TFWEPERM_POL_ACES A
                            INNER JOIN
                            TFWSPOL_ACES B
                            ON 
                            A.COD_POL_ACES = B.COD_POL_ACES");

                sql.AppendLine("WHERE");
                //filtrar as policies de forma a recuperar apenas as policies ativas
                sql.AppendLine("B.IND_SITU_POL_ACES = :IND_SITU_POL_ACES");
                this.DataBase.AddInParameter(command, "IND_SITU_POL_ACES", DbType.AnsiString,
                    EnumConverter.ToString<BusinessEntity.Enum.PolicyStatus>(BusinessEntity.Enum.PolicyStatus.Active));
                
                sql.AppendLine("AND A.COD_PERM IN (");
                for (int i = 0; i < roles.Count; i++)
                {
                    if (i == 0)
                        sql.AppendLine(string.Format(" :COD_PERM{0}", i.ToString()));
                    else
                        sql.AppendLine(string.Format(", :COD_PERM{0}", i.ToString()));

                    this.DataBase.AddInParameter(command, string.Format("COD_PERM{0}", i.ToString()), DbType.String, roles[i]);
                }                
                sql.AppendLine(")");

                command.CommandText = sql.ToString();

                response = this.FindAll<BusinessEntity.BehaviorPolicy>(command, new ConstructEntity<BusinessEntity.BehaviorPolicy>(ConstrutorBehaviorPolicy));
            }

            return response;
        }
        #endregion

        #region ConstrutorRetrieveBehaviorPolicies
        protected BusinessEntity.BehaviorPolicy ConstrutorBehaviorPolicy(IDataReader reader)
        {
            BusinessEntity.BehaviorPolicy entity = new BusinessEntity.BehaviorPolicy();

            entity.CompanyId = reader.GetValue<System.Int32?>("COMPANY_ID");

            entity.RoleId = reader.GetValue<System.String>("COD_PERM");

            entity.AssociatedPolicy = new Sinacor.Service.Infra.AuthorizationService.BusinessEntity.Policy();
            entity.AssociatedPolicy.PolicyId = reader.GetValue<System.Int32?>("COD_POL_ACES");
            entity.AssociatedPolicy.PolicyName = reader.GetValue<System.String>("NOME_POL_ACES");
            entity.AssociatedPolicy.PolicyStatus = EnumConverter.Parse<Sinacor.Service.Infra.AuthorizationService.BusinessEntity.Enum.PolicyStatus>(Convert.ToString(reader.GetValue<Int32>("IND_SITU_POL_ACES")));
            entity.AssociatedPolicy.PolicyType = EnumConverter.Parse<Sinacor.Service.Infra.AuthorizationService.BusinessEntity.Enum.PolicyType>(reader.GetValue<string>("COD_TIPO_POL_ACES"));


            entity.IsEditable = reader.GetValue<System.Int32>("IND_PERM_EDIC_DADO") == 1;
            entity.IsVisible = reader.GetValue<System.Int32>("IND_VISI_DADO") == 1;

            return entity;
        }
        #endregion

    }
}
